﻿#region [===== Using =====]
using System;
using System.Globalization;
#endregion

namespace TPG.SharePoint.Workflow
{
    /// <summary>
    /// A base control for controls which handle the form data 
    /// using the hosted control framework.
    /// </summary>
    /// <typeparam name="TData">The <see cref="System.Type"/> of the 
    /// data class.</typeparam>
    public abstract class WorkflowDataControl<TData>
        : WorkflowControl
    {
        #region [===== Fields =====]
        IWorkflowDataPage<TData> _page = null;
        #endregion

        #region [===== Properties =====]
        /// <summary>
        /// Gets or sets a value indicating the default mode of serialization 
        /// for the data object when the data requires serialization for 
        /// persistence.
        /// </summary>
        /// <remarks>
        /// Only configuration controls and modification controls make use of this
        /// settings since task data is not serialized but stored inside the 
        /// task list item.
        /// </remarks>
        public SerializationMode SerializationMode 
        {
            get { return (SerializationMode?)ViewState["SerializationMode"] ?? 
                SerializationMode.Xml; }
            set
            {
                if (Enum.IsDefined(typeof(SerializationMode), value) == false)
                {
                    throw new ArgumentOutOfRangeException();
                }
                ViewState["SerializationMode"] = value;
            }
        }
        #endregion

        #region [===== Constructors =====]
        /// <summary>
        /// Initializes a new instance of the 
        /// <see cref="WorkflowDataControl" /> class.
        /// </summary>
        protected WorkflowDataControl()
        {
        }
        #endregion

        #region [===== Protected methods =====]
        /// <summary>
        /// Initializes the control by checking if it is hosted inside a
        /// page belonging to the hosted control framework capable of handling
        /// the data type used by the WorkflowDataControl.
        /// </summary>
        /// <param name="e">An <see cref="System.EventArgs" /> containing 
        /// event data.</param>
        protected override void OnInit(EventArgs e)
        {
            _page = this.Page as IWorkflowDataPage<TData>;
            if (_page == null)
            {
                throw new WorkflowException(
                    String.Format(CultureInfo.CurrentCulture, "This control must be placed on a page implementing IWorkflowDataPage<{0}>.",
                        typeof(TData).AssemblyQualifiedName));
            }
            base.OnInit(e);
        }

        /// <summary>
        /// Indicates to the control that it should load the 
        /// form data by calling <see cref="WorkflowDataControl.LoadData" />.
        /// </summary>
        /// <param name="e">An <see cref="System.EventArgs" /> containing 
        /// event data.</param>
        /// <remarks>
        /// Note that the actual data itself is not provided. Instead you 
        /// should call <see cref="WorkflowDataControl.GetData" /> to retrieve
        /// the current form data. This prevents unnecessary loads of data 
        /// during bulk task operations.
        /// </remarks>
        protected override void OnLoad(EventArgs e)
        {
            LoadData(_page.IsInitialLoad);
            base.OnLoad(e);
        }

        /// <summary>
        /// Gets the current form data.
        /// </summary>
        /// <returns>The current form data.</returns>
        protected TData GetData()
        {
            return _page.GetData();
        }

        /// <summary>
        /// Loads the current form data.
        /// </summary>
        /// <param name="isInitialLoad">Indicates if the page is initialized
        /// for the first time or that a postback has occured.</param>
        protected abstract void LoadData(bool isInitialLoad);
        /// <summary>
        /// Saves the form data as a typed object.
        /// </summary>
        /// <param name="commandArgument">A parameter provided by the button 
        /// control which caused the page to save the data.</param>
        /// <returns>The form data as a typed object.</returns>
        protected internal abstract TData SaveData(object commandArgument);
        #endregion
    }
}
